from .utils import Version


class plugin_injector_compatibility:
    def __init__(self, minVer: str | None, maxVer: str | None):
        self.__minVer: Version | None = Version(minVer) if minVer else None
        self.__maxVer: Version | None = Version(maxVer) if maxVer else None
    
    def check_injector_version_compatibility(self, version: str | Version) -> bool:
        if not isinstance(version, version):
            version = version(version)
        if self.__minVer and self.__maxVer:
            return self.__minVer <= version <= self.__maxVer
        elif self.__minVer and not self.__maxVer:
            return self.__minVer <= version
        elif not self.__minVer and self.__maxVer:
            return version <= self.__maxVer

    @property
    def minVer(self) -> str | None:
        return str(self.__minVer) if self.__minVer else None
    @property
    def maxVer(self) -> str:
        return str(self.__maxVer) if self.__maxVer else None
    
    


class PluginCompatibility:
    def __init__(self, compatibility_dict: dict):
        self.__injector: plugin_injector_compatibility = plugin_injector_compatibility(
            compatibility_dict.get("injector", {}).get("minVer", "0.0.0"),
            compatibility_dict.get("injector", {}).get("maxVer", "999.999.999")
        )
    @property
    def injector(self):
        return self.__injector

class Task:
    def __init__(self, task_dict: dict):
        self.__type: str | None = task_dict.get("type")
        self.__from: str | None = task_dict.get("from")
        self.__to: str | None = task_dict.get("to")
    @property
    def type(self):
        return self.__type
    @property
    def from_path(self):
        return self.__from
    @property
    def to_path(self):
        return self.__to
    

class LoadMode:
    def __init__(self, loadmode_dict: dict):
        self.__onboot: list[Task] = [Task(t) for t in loadmode_dict.get("onboot", list())]
        self.__onload: list[Task] = [Task(t) for t in loadmode_dict.get("onload", list())]
    @property
    def onboot(self):
        return self.__onboot
    @property
    def onload(self):
        return self.__onload

class PluginLoad:
    def __init__(self, load_dict: dict):
        self.__symlink: bool = load_dict.get("symlink", False)
        self.__mode: LoadMode = LoadMode(load_dict.get("mode", dict()))
    @property
    def symlink(self):
        return self.__symlink
    @property
    def mode(self):
        return self.__mode
        

class PluginStartIcon:
    def __init__(self, icon_dict: dict):
        self.__name: str | None = icon_dict.get("path")
        self.__command: str | None = icon_dict.get("index")
        self.__icon: str | None = icon_dict.get("icon")
    @property
    def name(self):
        return self.__name
    @property
    def command(self):
        return self.__command
    @property
    def icon(self):
        return self.__icon
    

class PluginStart:
    def __init__(self, start_dict: dict):
        self.__icon: PluginStartIcon = PluginStartIcon(start_dict.get("type"), {})
        self.__path: list[str] = start_dict.get("path", list())
    @property
    def icon(self):
        return self.__icon
    @property
    def path(self):
        return self.__path

class PluginData:
    def __init__(self, data_dict: dict):
        self.__type: str | None = data_dict.get("type")
        self.__from: str | None = data_dict.get("from")
        self.__to: str | None = data_dict.get("to")
    @property
    def type(self):
        return self.__type
    @property
    def from_path(self):
        return self.__from
    @property
    def to_path(self):
        return self.__to


class PluginManifest:
    def __init__(self, manifest_dict: dict):
        self.__version: str = manifest_dict.get("version", "0.0.0")
        self.__name: str = manifest_dict.get("name", "Unnamed")
        self.__author: str = manifest_dict.get("author", "Unknown")
        self.__introduce: str = manifest_dict.get("introduce", "")
        self.__compatibility: PluginCompatibility = PluginCompatibility(manifest_dict.get("compatibility", {}))
        self.__load: PluginLoad = PluginLoad(manifest_dict.get("load", {}))
        self.__start: PluginStart = PluginStart(manifest_dict.get("start", {}))
        self.__reg: list[str] = manifest_dict.get("reg", list())
        self._keywords: list[str] = manifest_dict.get("keywords", list())
        self.__dependence: list[str] = manifest_dict.get("dependence", list())
        self.__datas: list[PluginData] = [PluginData(data) for data in manifest_dict.get("datas", list())]
    @property
    def version(self):
        return self.__version
    @property
    def name(self):
        return self.__name
    @property
    def author(self):
        return self.__author
    @property
    def introduce(self):
        return self.__introduce
    @property
    def compatibility(self):
        return self.__compatibility
    @property
    def load(self):
        return self.__load
    @property
    def start(self):
        return self.__start
    @property
    def reg(self):
        return self.__reg
    @property
    def keywords(self):
        return self._keywords
    @property
    def dependence(self):
        return self.__dependence
    @property
    def datas(self):
        return self.__datas


def to_plugin_manifest(d: dict) -> PluginManifest:
    return PluginManifest(d)